package com.mjk.manager.gen.work;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;

import cn.hutool.core.util.ClassUtil;
import com.mjk.common.base.error.BeeError;
import com.mjk.common.base.work.BaseWork;
import com.mjk.common.base.work.annotation.BeeWork;
import com.mjk.common.tools.logger.BizLogger;
import com.mjk.common.tools.springextend.BeeApplicationListener;
import com.mjk.common.util.AopTargetUtils;
import com.mjk.common.web.getway.restful.prototal.ws.soap.utils.SoapUtils;
import com.mjk.common.web.getway.transfer.GetwayTransfer;
import com.mjk.common.web.getway.transfer.http.HttpGetWayprotocol;
import com.mjk.manager.api.constns.ApiReturnType;
import com.mjk.manager.api.interceptor.ApiRetrunParamsInterceptor;
import com.mjk.manager.api.model.ApiModel;
import com.mjk.manager.gen.IGen;
import com.mjk.manager.gen.dto.GenDto;
import com.mjk.manager.gen.impl.interfaces.HttpGenImpl;
import com.mjk.manager.gen.impl.interfaces.InterfacesGen;
import com.mjk.manager.gen.impl.interfaces.WebServiceGenImpl;
import com.mjk.manager.gen.impl.ui.IUiGen;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.ContextRefreshedEvent;
import groovy.lang.GroovyClassLoader;

@BeeWork(work="gen")
public class GenWork extends BaseWork implements BeeApplicationListener {
	private ConfigurableApplicationContext context;
	
	@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
	@Autowired
	private GetwayTransfer getWayProtocol;
	
	@Autowired
	private ApiRetrunParamsInterceptor interceptor;
	/**
	 * ui生成得类
	 */
	private final List<IUiGen> uiGens = new ArrayList<>();
	/**
	 * 接口生成的类
	 */
	private WebServiceGenImpl webserviceGen ;
	
	private HttpGenImpl httpGen ;
	/**
	 * 页面生成
	 */
	public void doUiGen(GenDto dto) {
		for(IUiGen gen : uiGens) {
			if(gen.isVaild())
				gen.createClass(dto);
		}
		BeeError.BEE_SUC.tranceError();

	}

	/**
	 * 接口发布
     */
	public void publish(GenDto dto) {
		ApiModel model = dto.getModel();
		if("1".equals(model.getApiType())) {//http接口
			BeanDefinitionBuilder beanDefinitionBuilder;
			if("1".equals(model.getIsDynamic())) {//动态接口
				 beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(httpGen.createClass(dto));
			}else {
				Class clazz = ClassUtil.loadClass(model.getApiClazz());
				beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Objects.requireNonNull(clazz));
			}
			BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();			
			BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry) context.getBeanFactory();
			//是否存在bean定义
			if(beanFactory.containsBeanDefinition(model.getApiWork())){
				beanFactory.removeBeanDefinition(model.getApiWork());
			}
			beanFactory.registerBeanDefinition(model.getApiWork(), beanDefinition);	
			//替换work实例
			BeeWork work = Objects.requireNonNull(AopTargetUtils.getTarget(context.getBean(model.getApiWork()))).getClass().getAnnotation(BeeWork.class);
			if(getWayProtocol instanceof HttpGetWayprotocol httpProtocol) {
				httpProtocol.getWorkMapping().put(work.work().toUpperCase(), context.getBean(model.getApiWork()));
			}
			//修改返回类型
			if(ApiReturnType.NORMAL.getType().equals(model.getReturnType())){
				interceptor.returnTypeMap.put(model.getApiWork()+model.getApiMethod(), ApiReturnType.NORMAL.getType());
			}else if(ApiReturnType.JSONDATA.getType().equals(model.getReturnType())){
				interceptor.returnTypeMap.put(model.getApiWork()+model.getApiMethod(), ApiReturnType.JSONDATA.getType());
			}else if(ApiReturnType.XMLDATA.getType().equals(model.getReturnType())){
				interceptor.returnTypeMap.put(model.getApiWork()+model.getApiMethod(), ApiReturnType.XMLDATA.getType());
			}		
		}else if("2".equals(model.getApiType())) {//webservice接口
			GenDto tmp = new GenDto(model);
			tmp.setGroovyClassLoader(new GroovyClassLoader());
			Class<?> clazz = webserviceGen.createClass(tmp);
			SoapUtils.publish(clazz, model.getUrl(),tmp.getGroovyClassLoader());
		}
	}
	
	@Override
	public void doApplicationEvent(ContextRefreshedEvent event) {
		context = (ConfigurableApplicationContext)event.getApplicationContext();
		Set<Class<?>> clazzs = ClassUtil.scanPackageBySuper("com.mjk.manager.gen.impl", IGen.class);
		for(Class<?> clazz : clazzs) {
			try {
				if(IUiGen.class.isAssignableFrom(clazz) && !clazz.isInterface()) {
					uiGens.add((IUiGen)clazz.newInstance());
				}
				if(InterfacesGen.class.isAssignableFrom(clazz) && !clazz.isInterface()) {
					Object obj = clazz.newInstance();
					if(obj instanceof WebServiceGenImpl imp) {
						webserviceGen = imp;
					}else if( obj instanceof HttpGenImpl imp) {
						httpGen = imp;
					}
				}
			}catch(Exception e) {
				BizLogger.error(e);
			}
		}
	}
}
